using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Diagnostics;

namespace AnimalWars2
{
    public class Game : Microsoft.Xna.Framework.Game
    {
        public GraphicsDeviceManager m_graphics;
        public SpriteBatch m_spriteBatch;

        public SpriteFont m_Font;

        public Texture2D m_DebugCircle;
        public Texture2D m_DebugLine;

        private GameScreen m_CurrentScreen;

        public GameTable m_GameTable;
        public GameMenu m_GameMenu;
        public GameMap m_GameMap;

        public Camera m_Camera = null;

        private GameState m_GameState;
        private Boolean lastPauseKeyState = false;

        public Game()
        {
            m_graphics = new GraphicsDeviceManager(this);

            m_graphics.PreferredBackBufferWidth = Constants.WINDOW_WIDTH;
            m_graphics.PreferredBackBufferHeight = Constants.WINDOW_HEIGHT;
            m_graphics.ApplyChanges();

            Content.RootDirectory = Constants.CONTENT_ROOT_DIRECTORY;

            IsMouseVisible = true;

            init();
        }

        private void init()
        {
            m_GameMenu = new GameMenu(this);
            m_GameMap = new GameMap(this);
            m_GameTable = new GameTable(this, VisualizationMode.Perspective);

            m_CurrentScreen = m_GameMenu;

            m_GameState = GameState.Playing;
        }

        public void ChangeScreen(GameScreen newGameScreen)
        {
            m_CurrentScreen.UnloadContent();
            newGameScreen.LoadContent();

            m_CurrentScreen = newGameScreen;

            if (newGameScreen is GameTable)
            {               
                m_GameTable.startGame();
            }
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            m_spriteBatch = new SpriteBatch(GraphicsDevice);

            m_DebugCircle = Content.Load<Texture2D>(Constants.DEBUG_CIRCLE_ASSET_NAME);

            m_Camera = new Camera(this, new Vector2(0.0f, 0.0f), m_DebugCircle, VisualizationMode.Top);

            m_Font = Content.Load<SpriteFont>(Constants.GAME_FONT_ASSET_NAME);

            m_DebugLine = new Texture2D(GraphicsDevice, 1, 1, false, SurfaceFormat.Color);
            Color[] pixels = new Color[1];
            pixels[0] = Color.White;
            m_DebugLine.SetData<Color>(pixels);

            m_GameMenu.LoadContent();
        }

        protected override void UnloadContent()
        {
            m_GameMenu.UnloadContent();
            m_GameMap.UnloadContent();
            m_GameTable.UnloadContent();
        }

        private void SwitchPause()
        {
            if (m_GameState == GameState.Playing)
            {
                m_GameState = GameState.Paused;
            }
            else
            {
                m_GameState = GameState.Playing;
            }
        }

        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                Exit();

            KeyboardState keyboardState = Keyboard.GetState();

            if (!lastPauseKeyState && keyboardState.IsKeyDown(Keys.P))
            {
                SwitchPause();
            }

            if (m_GameState == GameState.Playing)
            {
                m_CurrentScreen.Update(gameTime);
                
                m_Camera.m_VisualizationMode = m_GameTable.m_VisualizationMode;
                m_Camera.Update(gameTime);

                base.Update(gameTime);
            }

            lastPauseKeyState = keyboardState.IsKeyDown(Keys.P);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            m_spriteBatch.Begin(SpriteSortMode.Immediate,
                                BlendState.AlphaBlend,
                                SamplerState.LinearClamp,
                                DepthStencilState.None,
                                RasterizerState.CullNone);

            m_CurrentScreen.Draw(gameTime, m_spriteBatch);

            if (m_GameState == GameState.Paused)
            {
                DrawGamePaused(gameTime);
            }
            
            m_spriteBatch.End();            
        }

        protected void DrawGamePaused(GameTime gameTime)
        {
            StringUtils.DrawString(m_Font, m_spriteBatch, "Game Paused...", 0, 0);
        }

        public void DrawLine(SpriteBatch oSpriteBatch, Vector2 vSrc, Vector2 vTgt, Color oColor, float Depth)
        {
            float distance = Vector2.Distance(vSrc, vTgt);

            float angle = (float)Math.Atan2((double)(vTgt.Y - vSrc.Y), (double)(vTgt.X - vSrc.X));

            oSpriteBatch.Draw(m_DebugLine, vSrc, null, oColor, angle, Vector2.Zero, new Vector2(distance, 1), SpriteEffects.None, Depth);
        }
    }
}
